package cn.tedu.v3;

import java.io.*;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

/**
 * Version 3.0  升级   双向链接【客户端与服务器相互说话】
 *
 * 优化空间: 代码结构、流没有关闭
 */
public class Server {
    private ServerSocket serverSocket;
    public Server(){
        try {
            serverSocket=new ServerSocket(6666);
        } catch (BindException e){
            System.out.println("端口号重复申请，建议换个端口号");
        } catch (IOException e) {
            System.out.println("申请端口号失败...");
        }
    }

    public void start()  {
        try {
            while (true){
            System.out.println("-------等待客户端链接------");
            Socket socket = serverSocket.accept();
            String ip=socket.getInetAddress().getHostAddress();
            System.out.println("一个客户端链接成功了~~~");

                new Thread(new CS(socket)).start();
            }
        } catch (IOException e) {
            System.out.println("服务器端通讯断开");
        } finally {
            if (serverSocket!=null&&!serverSocket.isClosed()){
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    System.out.println("服务器关闭失败");
                }
            }
        }
    }
    public static void main(String[] args)  {
        new Server().start();
    }

    private class CS implements Runnable{
        private Socket socket;
        private String ip;
        public CS(Socket s){
            this.socket=s;
            ip=socket.getInetAddress().getHostAddress();
        }

        public void run() {
            //读入
            // BufferedReader br=null;
            //写出
            PrintWriter pw = null;
            try {
            //1.读入定义
            BufferedReader br=new BufferedReader(new InputStreamReader
                    (socket.getInputStream(),"UTF8"));
            //2.写出定义
             pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter
                     (socket.getOutputStream(),
                          "UTF8")), true);
            String str=null;
            //1.1 读入功能:存线程中
             new Thread(()->{
                 try{
                 String message;
                 while ((message=br.readLine())!=null){
                     System.out.println("客户端说: "+message);
                     // 增加写出一句话: 读完卡住等待输入
                     System.out.println("服务器端请输入: ");
                 }
                 }catch (IOException e){
                     System.out.println("客户端读入失败!");
                 }
             }).start();
             //2.1 提供写的方法: 控制台输入功能
               Scanner input=new Scanner(System.in); // 后台卡住
                while(true){
                    System.out.println(ip+"服务器请输入: ");
                    String say=input.nextLine(); //得到控制台输入的值
                    //打印: 服务器端说的文本---打印客户端
                    pw.println("服务器说: "+say);
                }

                /*new Thread(()->{
                    Scanner input = new Scanner(System.in);
                    while (true){
                        pw.println(input.nextLine());
                        System.out.println("写出成功");
                    }
                }).start();*/

            /*while (true){
                str=br.readLine();
                System.out.println(ip+"客户端说的话: "+str);
            }*/
            } catch (NullPointerException e) {
                System.out.println("IO流传输对象，有对象为null,请立马核对。"
                        +"建议: 查看try块中对象可能赋值为null");
            } catch (UnsupportedEncodingException e) {
                System.out.println("客户端或者服务器端: 字符集不一致");
            } catch (IOException e) {
                System.out.println("通讯过程中，传输出现错误!");
            } finally {
              /* if (br!=null)
                    try {
                        br.close();
                    } catch (IOException e) {
                        System.out.println("结束通讯: 关闭失败!");
                    }*/
                if (socket!=null&&!socket.isClosed()){
                    try {
                        socket.close();
                    } catch (IOException e) {
                        System.out.println("通讯关闭失败~");
                    }
                }
            }
        }
    }
}
